﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.IdentityModel.Claims;

namespace Microsoft.IdentityModel.OAuth
{
    internal class SWTParser
    {
        private string issuerLabel = "Issuer";
        private string expiresLabel = "ExpiresOn";
        private string audienceLabel = "Audience";
        private string hmacSHA256Label = "HMACSHA256";
		// JBurnett, 08/20/2010: changed to match Azure's response
		//		private const string tokenPrefix = "WRAP access_token";
		private const string tokenPrefix = "wrap_access_token";

        IDictionary<string, string> dictionary;
        public SWTParser(string urlDecodedSWT)
        {
            dictionary = Parse(urlDecodedSWT);
        }

        string GetValue(string key)
        {
            return dictionary.GetAndRemove(key);
        }

        public List<Claim> Claims
        {
            get
            {
                return
                    dictionary.Where(e =>
                        e.Key != issuerLabel &&
                        e.Key != expiresLabel &&
                        e.Key != audienceLabel &&
                        e.Key != hmacSHA256Label).Select(kv =>
                            new Claim(kv.Key, kv.Value)).ToList();
            }
        }


        public string Issuer { get { return dictionary[issuerLabel]; } }

        public string Audience { get { return dictionary[audienceLabel]; } }

        public static Dictionary<string, string> Parse(string token)
        {
            if (string.IsNullOrEmpty(token))
            {
                throw new ArgumentException();
            }

            return
                token
                .Split('&')
                .Aggregate(
                new Dictionary<string, string>(),
                (dict, rawNameValue) =>
                {
                    if (rawNameValue == string.Empty)
                    {
                        return dict;
                    }

                    string[] nameValue = rawNameValue.Split('=');

                    if (nameValue.Length != 2)
                    {
                        throw new ArgumentException("Invalid formEncodedstring - contains a name/value pair missing an = character");
                    }

                    if (dict.ContainsKey(nameValue[0]) == true)
                    {
                        throw new ArgumentException("Repeated name/value pair in form");
                    }

                    dict.Add(nameValue[0].UrlDecode(), nameValue[1].UrlDecode());
                    return dict;
                });
        }

        public static string ExtractAndDecodeAccessToken(string authorizationHeader)
        {
            if (string.IsNullOrEmpty(authorizationHeader) ||
                !authorizationHeader.StartsWith(tokenPrefix, StringComparison.OrdinalIgnoreCase))
            {
                return null;
            }
            authorizationHeader = authorizationHeader.Remove(0, tokenPrefix.Length).TrimStart(' ');
            if (authorizationHeader[0] != '=')
            {
                return null;
            }

            var accessToken = authorizationHeader.TrimStart('=', ' ');
            return HttpUtility.UrlDecode(accessToken);
        }
    }
}
